<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\App\Corp\Action\Dashboard;

use Exception;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\Middlewares;
use Hyperf\HttpServer\Annotation\RequestMapping;
use MoChat\App\Common\Middleware\DashboardAuthMiddleware;
use MoChat\App\Corp\Contract\CorpContract;
use MoChat\App\Utils\Url;
use MoChat\Framework\Action\AbstractAction;
use MoChat\Framework\Request\ValidateSceneTrait;

/**
 * 企业微信授权- 接受事件服务器详情.
 *
 * Class ContactSecretStore.
 * @Controller
 */
class CallbackInfo extends AbstractAction
{
    use ValidateSceneTrait;

    /**
     * @Inject
     * @var CorpContract
     */
    protected $corpService;

    /**
     * @RequestMapping(path="/dashboard/corp/callbackInfo", methods="get")
     * @Middlewares({
     *     @Middleware(DashboardAuthMiddleware::class)
     * })
     * @return array|
     * @throws Exception 异常处理
     */
    public function handle()
    {
        // 接收参数
        $params['type'] = (int) $this->request->input('type', 1);
        $params['corpId'] = (int) user()['corpIds'][0];
        $this->validated($params, 'store');

        if ($params['type'] === 1) {
            $info = $this->corpService->getCorpById((int) $params['corpId'], ['token', 'encoding_aes_key']);
            if (empty($info['token'])) {
                $info = $this->getTokenKey($params['corpId']);
            }
        }

        if ($params['type'] === 2) {
            $info = $this->getTokenKey($params['corpId']);
        }

        $info['eventCallback'] = Url::getApiBaseUrl() . '/' . ltrim(config('framework.wework.callback_path'), '/') . '?cid=' . $params['corpId'];
        $info['OAuthDomain'] = parse_url(Url::getApiBaseUrl(), PHP_URL_HOST);
        $info['jssdkDomain'] = parse_url(Url::getSidebarBaseUrl(), PHP_URL_HOST);
        return $info;
    }

    /**
     * 验证规则.
     *
     * @return array 响应数据
     */
    protected function rules(): array
    {
        return [
            'corpId' => 'required | integer | min:0 | bail',
        ];
    }

    /**
     * 验证错误提示.
     * @return array 响应数据
     */
    protected function messages(): array
    {
        return [
            'corpId.required' => '企业ID 必填',
            'corpId.integer' => '企业ID 必须为整型',
        ];
    }

    private function getTokenKey(int $corpId): array
    {
        // 回调token
        $tokenKey = random_bytes(random_int(1, 24));
        $info['token'] = str_replace(['/', '+', '='], '', base64_encode($tokenKey));
        // 回调消息加密串
        $info['encodingAesKey'] = $this->getAesKeyStr();

        $this->corpService->updateCorpById($corpId, [
            'token' => $info['token'],
            'encoding_aes_key' => $info['encodingAesKey'],
        ]);
        return $info;
    }

    /**
     * 生成43位aesKey的base64字符串.
     */
    private function getAesKeyStr(): string
    {
        $baseChars = [
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        ];
        shuffle($baseChars);

        return implode('', array_slice($baseChars, 0, 43));
    }
}
